RealtimeChart   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 13
eloc 140
dl 0
loc 173
rs 10
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
A componentWillUnmount 0 5 1
B render 0 45 1
D componentDidMount 0 102 11
1
import React, { Component } from 'react';
2
import { Line } from 'react-chartjs-2';
3
import range from 'lodash/range';
4
import { Card, CardHeader, CardBody, ListGroup, ListGroupItem } from 'reactstrap';
5
import { rgbaColor } from '../../../helpers/utils';
6
import { withTranslation } from 'react-i18next';
7
import uuid from 'uuid/v1';
8
import { APIBaseURL } from '../../../config';
9
import { getCookieValue, createCookie } from '../../../helpers/utils';
10
import { toast } from 'react-toastify';
11
12
13
const dividerBorder = '1px solid rgba(255, 255, 255, 0.15)';
14
const listItemBorderColor = 'rgba(255, 255, 255, 0.05)';
15
16
const chartOptions = {
17
  legend: { display: false },
18
  scales: {
19
    yAxes: [
20
      {
21
        display: true,
22
        stacked: false
23
      }
24
    ],
25
    xAxes: [
26
      {
27
        stacked: false,
28
        ticks: { display: false },
29
        categoryPercentage: 1.0,
30
        gridLines: {
31
          color: rgbaColor('#fff', 0.1),
32
          display: true
33
        }
34
      }
35
    ]
36
  }
37
};
38
39
class RealtimeChart extends Component {
40
  _isMounted = false;
41
  refreshInterval;
42
  refreshTimeout;
43
  state = {
44
    trendLog: [],
45
    currentEnergyValue: undefined,
46
    chartData: {
47
      labels: range(1, 60),
48
      datasets: [
49
        {
50
          label: '',
51
          backgroundColor: rgbaColor('#fff', 0.3),
52
        }
53
      ]
54
    },
55
    pointList: [],
56
  };
57
58
  componentWillUnmount() {
59
    this._isMounted = false;
60
    clearInterval(this.refreshInterval);
61
    clearTimeout(this.refreshTimeout);
62
  }
63
64
  componentDidMount() {
65
    this._isMounted = true;
66
    // fetch meter realtime data at the first time
67
    let isResponseOK = false;
68
    fetch(APIBaseURL + '/reports/meterrealtime?meterid=' + this.props.meterId, {
69
      method: 'GET',
70
      headers: {
71
        "Content-type": "application/json",
72
        "User-UUID": getCookieValue('user_uuid'),
73
        "Token": getCookieValue('token')
74
      },
75
      body: null,
76
77
    }).then(response => {
78
      if (response.ok) {
79
        isResponseOK = true;
80
      }
81
      return response.json();
82
    }).then(json => {
83
      if (isResponseOK) {
84
        console.log(json);
85
        let trendLog = json['energy_value']['values'];
86
        let currentEnergyValue = undefined;
87
        let pointList = [];
88
        if (trendLog.length > 0) {
89
          currentEnergyValue = trendLog[trendLog.length - 1];
90
        }
91
        json['parameters']['names'].forEach((currentName, index) => {
92
          let pointItem = {}
93
          pointItem['name'] = currentName;
94
          pointItem['value'] = undefined;
95
          let currentValues = json['parameters']['values'][index];
96
          if (currentValues.length > 0) {
97
            pointItem['value'] = currentValues[currentValues.length - 1];
98
          }
99
          pointList.push(pointItem);
100
        });
101
        if (this._isMounted) {
102
          this.setState({ 
103
            trendLog: trendLog, 
104
            currentEnergyValue: currentEnergyValue,
105
            pointList: pointList,
106
          });
107
        }
108
      } else {
109
        toast.error(json.description)
110
      }
111
    }).catch(err => {
112
      console.log(err);
113
    });
114
115
    //fetch meter realtime data at regular intervals
116
    this.refreshInterval = setInterval(() => {
117
      let isResponseOK = false;
118
      fetch(APIBaseURL + '/reports/meterrealtime?meterid=' + this.props.meterId, {
119
        method: 'GET',
120
        headers: {
121
          "Content-type": "application/json",
122
          "User-UUID": getCookieValue('user_uuid'),
123
          "Token": getCookieValue('token')
124
        },
125
        body: null,
126
127
      }).then(response => {
128
        if (response.ok) {
129
          isResponseOK = true;
130
        }
131
        return response.json();
132
      }).then(json => {
133
        if (isResponseOK) {
134
          console.log(json);
135
          let trendLog = json['energy_value']['values'];
136
          let currentEnergyValue = undefined;
137
          let pointList = [];
138
          if (trendLog.length > 0) {
139
            currentEnergyValue = trendLog[trendLog.length - 1];
140
          }
141
          json['parameters']['names'].forEach((currentName, index) => {
142
            let pointItem = {}
143
            pointItem['name'] = currentName;
144
            pointItem['value'] = undefined;
145
            let currentValues = json['parameters']['values'][index];
146
            if (currentValues.length > 0) {
147
              pointItem['value'] = currentValues[currentValues.length - 1];
148
            }
149
            pointList.push(pointItem);
150
          });
151
          if (this._isMounted) {
152
            this.setState({ 
153
              trendLog: trendLog, 
154
              currentEnergyValue: currentEnergyValue,
155
              pointList: pointList,
156
            });
157
          }
158
        } else {
159
          toast.error(json.description)
160
        }
161
      }).catch(err => {
162
        console.log(err);
163
      });
164
    }, (60 + Math.floor(Math.random() * Math.floor(10))) * 1000); // use random interval to avoid paralels requests 
165
  }
166
167
  render() {
168
    const { t } = this.props;
169
    const chartData = {
170
      ...this.state.chartData,
171
      datasets: [
172
        {
173
          ...this.state.chartData.datasets[0],
174
          data: this.state.trendLog
175
        }
176
      ]
177
    };
178
179
    return (
180
      <Card className="h-100 bg-gradient">
181
        <CardHeader className="bg-transparent">
182
          <h5 className="text-white">{this.props.meterName}</h5>
183
          <div className="real-time-user display-1 font-weight-normal text-white">{this.state.currentEnergyValue}</div>
184
        </CardHeader>
185
        <CardBody className="text-white fs--1">
186
          <p className="pb-2" style={{ borderBottom: dividerBorder }}>
187
          {t('Trend in the last hour of Energy Value Point (UNIT)', {'UNIT': 'kWh'})}
188
          </p>
189
          <Line data={chartData} options={chartOptions} width={10} height={4} />
190
          <ListGroup flush className="mt-4">
191
          
192
            <ListGroupItem
193
              className="bg-transparent d-flex justify-content-between px-0 py-1 font-weight-semi-bold border-top-0"
194
              style={{ borderColor: listItemBorderColor }}
195
            >
196
              <p className="mb-0">{t('Related Parameters')}</p>
197
              <p className="mb-0">{t('Realtime Value')}</p>
198
            </ListGroupItem>
199
            {this.state.pointList.map(pointItem => (
200
              <ListGroupItem key={uuid()}
201
                className="bg-transparent d-flex justify-content-between px-0 py-1"
202
                style={{ borderColor: listItemBorderColor }}
203
              >
204
                <p className="mb-0">{pointItem['name']}</p>
205
                <p className="mb-0">{pointItem['value']}</p>
206
              </ListGroupItem>
207
            ))}
208
          </ListGroup>
209
        </CardBody>
210
      </Card>
211
    );
212
  }
213
}
214
215
export default  withTranslation()(RealtimeChart);
216